/**
  1、数据类型：
    * 数据分为基本的数据类型(String, Number, Boolean, Null, Undefined)和对象数据类型
    - 基本数据类型：
      特点： 存储的是该对象的实际数据
    - 对象数据类型：
      特点： 存储的是该对象在栈中引用，真实的数据存放在堆内存里
  2、复制数据
    - 基本数据类型存放的就是实际的数据，可直接复制
      let number2 = 2;
      let number1 = number2;
    - 克隆数据：对象/数组
      1、区别： 浅拷贝/深度拷贝
         判断： 拷贝是否产生了新的数据还是拷贝的是数据的引用
         知识点：对象数据存放的是对象在栈内存的引用，直接复制的是对象的引用
         let obj = {username: 'kobe'}
         let obj1 = obj; // obj1 复制了obj在栈内存的引用
      2、常用的拷贝技术
        1). arr.concat(): 数组浅拷贝
        2). arr.slice(): 数组浅拷贝
        3). JSON.parse(JSON.stringify(arr/obj)): 数组或对象深拷贝, 但不能处理函数数据
        4). 浅拷贝包含函数数据的对象/数组
        5). 深拷贝包含函数数据的对象/数组
 */

//arr.concat(): 数组浅拷贝
const arr1 = [1,2,3,{name:'limi'}]
const arr2 = arr1.concat(4)
//console.log(arr2)//[ 1, 2, 3, { name: 'limi' }, 4 ]
arr2[3].name = 'hamey'
//console.log(arr1)//[ 1, 2, 3, { name: 'hamey' } ]
//console.log(arr2)//[ 1, 2, 3, { name: 'hamey' }, 4 ]

//arr.slice(): 数组浅拷贝
const arr3 = arr1.slice(3, 4)
// console.log(arr3) //[ { name: 'hamey' } ]
arr3[0].name = 'limi'
// console.log(arr1)//[ 1, 2, 3, { name: 'limi' } ]
// console.log(arr3)//[ { name: 'limi' } ]

// Object.assign();  浅复制
const obj1 = {name:'limi', age:31, a: {b: 1}}
const obj2 = {}
Object.assign(obj2, obj1)
// console.log(obj2)//{ name: 'limi', age: 31, a: { b: 1 } }
obj2.a.b = 30
// console.log(obj1, obj2)//{ name: 'limi', age: 31, a: { b: 30 } } { name: 'limi', age: 31, a: { b: 30 } }

//深度克隆(复制)
function getObjClass(obj) {
  //获取对象的类型
  const type = Object.prototype.toString.call(obj).slice(8, -1)
  if (type === 'Null') {
    return 'Null'
  } else if (type === 'Undefined') {
    return 'Undefined'
  } else {
    return type
  }
}

//深度克隆
function deepClone(obj) {
  let result, type = getObjClass(obj)
  if (type === 'Object') {
    result = {}
  } else if (type === 'Array') {
    result = []
  } else {
    return obj // 如果是其他数据类型不复制，直接将数据返回
  }

  //遍历模板对象
  for(let key in obj) {
    let value = obj[key]
    if (getObjClass(value) === 'Object' || 'Array') {
      result[key] = deepClone(value)
    } else {
      result[key] = value
    }
  }

  return result
}

let obj3 = {username: 'Bob',age: 20, sex: {option1: '男', option2: '女'}}
let obj4 = deepClone(obj3)
console.log(obj4)
obj4.sex.option1 = '不男不女' // 修改复制后的对象不会影响原对象
console.log(obj4, obj3)